#include "adalog/appender/RollFileAppender.h"
#include "adalog/LogEvent.h"
#include "adalog/Logger.h"
#include <chrono>
#include <filesystem>
#include <sstream>
#include <thread>

namespace fs = std::filesystem;

namespace adalog
{
    RollFileAppender::RollFileAppender(const std::filesystem::path& file_path, size_t max_size)
        : file_path_(file_path)
        , max_file_size_(max_size)
        , counter_(1)
    {
        try 
        {
            if (!fs::exists(file_path.parent_path()))
                fs::create_directories(file_path.parent_path());
        }
        catch (const fs::filesystem_error& e)
        {
            ADALOG_DEFAULT_ERROR(e.what());
        }
    }

    RollFileAppender::~RollFileAppender()
    {
        if(os_.is_open())
            os_.close();
    }

    void RollFileAppender::Append(const char* data, size_t len)
    {
        std::unique_lock<std::mutex> lock(mtx_);
        if (!os_.is_open() || fs::file_size(last_open_file_path_) > max_file_size_)
        {
            if (os_.is_open())
                os_.close();
            std::string file_name = file_path_.filename().string() 
                                    + GetCurrentTimeString() + "-" + std::to_string(counter_++) + ".log";
            fs::path file_dir = file_path_.parent_path();
            fs::path new_file_path = file_dir / file_name;
            os_.open(new_file_path, std::ios::app);
            last_open_file_path_ = new_file_path;
            if (!os_.is_open())
            {
                ADALOG_DEFAULT_ERROR("Can not open file: " + new_file_path.string());
            }
        }
        os_.write(data, len);
    }

    std::string RollFileAppender::GetCurrentTimeString()
    {
        auto now = std::chrono::system_clock::now();
        auto now_time = std::chrono::system_clock::to_time_t(now);
        std::tm local_tm = *std::localtime(&now_time);
        std::stringstream ss;
        ss << std::put_time(&local_tm, "%Y%m%d%H%M%S");
        return ss.str();
    }

} // namespace adalog